package com.sunwayworld.basemodule.business.pjtask.computing.formula;

import com.sunwayworld.basemodule.business.pjtask.bean.LimsPjTaskBean;
import com.sunwayworld.basemodule.business.pjtask.computing.PjTaskComputingEngine;
import com.sunwayworld.basemodule.samplemanage.sample.bean.LimsSampleBean;
import com.sunwayworld.framework.exception.FormulaException;
import com.sunwayworld.framework.formula.GikamComputingDataHolder;
import com.sunwayworld.framework.utils.*;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.OptionalDouble;
import java.util.stream.Collectors;

public class PjTaskFormulaRepository {
    /**
     * 获取当前处理中的样品结果
     */
    public static LimsPjTaskBean getCurrent() {
        return GikamComputingDataHolder.getCurrentData();
    }

    // 获取 当前样本 某检测项的结果 String
    public static String RS(String item) {
        LimsPjTaskBean taskBean = getTaskResult(item);
        return taskBean == null ? null : taskBean.getFinalResult();
    }

    // 获取 当前样本 某检测项的结果 double
    public static Double RN(String item) {
        LimsPjTaskBean resultBean = getTaskResult(item);
        return parseDouble(BeanUtils.getPropertyValue(resultBean, "finalResult"));
    }

    // 获取 当前样本检测项的某个属性值
    public static String RR(String item, String param) {
        LimsPjTaskBean resultBean = getTaskResult(item);
        Object propertyValue = BeanUtils.getPropertyValue(resultBean, param);
        return propertyValue == null ? null : propertyValue.toString();
    }

    // 去掉非数字，然后转double
    public static Double PD(String txt) {
        if(NumberUtils.isNumber(txt)){
            return NumberUtils.parseDouble(txt);
        }
        return 0d;
    }

    // 去掉非数字，然后转double
    private static Double parseDouble(String txt) {
        if(NumberUtils.isNumber(txt)){
            return NumberUtils.parseDouble(txt);
        }
        return 0d;
    }

    // 计算最小值
    public static Double min(String... args) {
        if(args == null) {
            return null;
        }
        List<String> list = Arrays.asList(args);
        OptionalDouble min = list.stream().mapToDouble(PjTaskFormulaRepository::parseDouble).min();
        return min.orElse(0.0);
    }

    // 计算最大值
    public static Double max(String... args) {
        if(args == null) {
            return null;
        }
        List<String> list = Arrays.asList(args);
        OptionalDouble max = list.stream().mapToDouble(PjTaskFormulaRepository::parseDouble).max();
        return max.orElse(0.0);
    }

    // 计算平均值
    public static Double avg(String... args) {
        if(args == null) {
            return null;
        }
        List<String> list = Arrays.asList(args);
        OptionalDouble average = list.stream().mapToDouble(PjTaskFormulaRepository::parseDouble).average();
        return average.orElse(0.0);
    }

    // 计算和
    public static Double sum(String... args) {
        if(args == null) {
            return null;
        }
        List<String> list = Arrays.asList(args);
        return list.stream().mapToDouble(PjTaskFormulaRepository::parseDouble).sum();
    }

    // 保留2位小数
    public static Double ps(Double a) {
        BigDecimal two = new BigDecimal(a);
        return two.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    // 除法
    public static Double div(String a, String b) {
        return ArithUtils.div(a, b);
    }

    // 求平方差
    public static Double evp(String... args) {
        if(args == null) {
            return null;
        }
        Double avg = avg(args);
        List<String> list = Arrays.asList(args);
        double sum = list.stream().map(PjTaskFormulaRepository::parseDouble).map(t -> (t - avg) * (t - avg)).mapToDouble(t -> t).sum();
        return ps(sum/list.size());
    }

    // 获取 当前样本的属性值 字符串
    public static String SS(String propertyName){
        LimsPjTaskBean taskResult = getCurrent();
        List<LimsSampleBean> sampleBeanList = GikamComputingDataHolder.get(PjTaskComputingEngine.FOLDER_SAMPLE_LIST);
        LimsSampleBean sampleBean = sampleBeanList.stream()
                .filter(r -> ObjectUtils.equals(r.getSampleCode(), taskResult.getExt$Item("sampleCode")))
                .findFirst().orElse(null);

        Object propertyValue = BeanUtils.getPropertyValue(sampleBean, propertyName);
        return propertyValue == null ? null : propertyValue.toString();
    }

    // 获取 当前样本的属性值 数值
    public static Double SN(String propertyName){
        LimsPjTaskBean taskResult = getCurrent();
        List<LimsSampleBean> sampleBeanList = GikamComputingDataHolder.get(PjTaskComputingEngine.FOLDER_SAMPLE_LIST);
        LimsSampleBean sampleBean = sampleBeanList.stream()
                .filter(r -> ObjectUtils.equals(r.getSampleCode(), taskResult.getExt$Item("sampleCode")))
                .findFirst().orElse(null);

        return parseDouble(BeanUtils.getPropertyValue(sampleBean, propertyName));
    }

    // 获取 当前样本的属性值 数值
    public static LocalDateTime ST(String propertyName){
        LimsPjTaskBean taskResult = getCurrent();
        List<LimsSampleBean> sampleBeanList = GikamComputingDataHolder.get(PjTaskComputingEngine.FOLDER_SAMPLE_LIST);
        LimsSampleBean sampleBean = sampleBeanList.stream()
                .filter(r -> ObjectUtils.equals(r.getSampleCode(), taskResult.getExt$Item("sampleCode")))
                .findFirst().orElse(null);
        return BeanUtils.getPropertyValue(sampleBean, propertyName);
    }

    public static String TDD(LocalDateTime time, int day) {
        LocalDateTime time1 = time.plusDays(day);
        return DateTimeUtils.formatLocalDateTime(time1);
    }

    public static String sub(String s, int start, int end){
        return s.substring(start, end);
    }

    public static String subEnd(String s, int start){
        if(s.length() < start) return null;
        return s.substring(s.length() - start);
    }

    public static String subEnd(String s, int start, int end){
        if(s.length() < start) return null;
        return s.substring(s.length() - end, s.length() - start);
    }


    public static boolean NN(Object prop){
        return Objects.isNull(prop);
    }

    public static boolean eq(String a, String b){
        return a.equals(b);
    }

    public static boolean eql(String a, String b){
        return a.equalsIgnoreCase(b);
    }

    public static boolean ct(String a, String b){
        return StringUtils.contains(a, b);
    }

    public static boolean ctl(String a, String b){
        return StringUtils.containsIgnoreCase(a, b);
    }

    public static double ln(Double a){
        return Math.log(a);
    }

    public static double lg(Double a){
        return Math.log10(a);
    }


    /**
     * 把数据修约之后的结果返回
     *
     * @param roundtype
     *            修约类型，必输项。
     * @param picture
     *            修约长度，必输项。
     * @param value
     *            要修约的数，必输项。
     */
    public static String getRounding(String roundtype, String picture, String value) {
        return NumberUtils.rounding(value, roundtype + "," + picture);
    }


    // -----------------------------------------------------------------------
    // 私有方法
    // -----------------------------------------------------------------------
    private static List<LimsPjTaskBean> getTaskResultList(String... args) {
        if (args.length == 0) {
            throw new FormulaException("MODULE.BUSINESS.RESULT.TIP.FORMULA_REQUIRE_ITEMNAME");
        }

        if (StringUtils.isEmpty(args[0])) {
            throw new FormulaException("MODULE.BUSINESS.RESULT.TIP.FORMULA_REQUIRE_ITEMNAME");
        }

        LimsPjTaskBean taskResult = getCurrent();

        // 检测项目编码
        String itemName = args[0];

        List<LimsPjTaskBean> pjTaskBeans = GikamComputingDataHolder.get(PjTaskComputingEngine.FOLDER_ORDER_TASK_PJ_LIST);
        return pjTaskBeans.stream()
                .filter(r -> ObjectUtils.equals(itemName, r.getPurposeCode()) && ObjectUtils.equals(taskResult.getFolderId(), r.getFolderId()))
                .collect(Collectors.toList());
    }

    private static LimsPjTaskBean getTaskResult(String item) {
        LimsPjTaskBean taskResult = getCurrent();

        List<LimsPjTaskBean> orderTaskResultList = GikamComputingDataHolder.get(PjTaskComputingEngine.FOLDER_ORDER_TASK_PJ_LIST);
        return orderTaskResultList.stream()
                .filter(r -> ObjectUtils.equals(item, r.getPurposeCode()) && ObjectUtils.equals(taskResult.getFolderId(), r.getFolderId()))
                .findFirst().orElse(null);
    }

}
